﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace Love.Awesome.FluxNET
{
    /// <summary>
    /// 过渡动画管理器，是整个程序的入口。
    /// </summary>
    public class Flux : IEnumerable<Tween>
    {

        private static Color[] _debugColorParttern = new Color[]
        {
            Color.Red, Color.LightGreen, Color.LightPink, Color.Yellow, Color.LemonChiffon, Color.Orange, Color.Aqua,Color.LightYellow
        };

        /// <summary>
        /// 原作的项目地址。
        /// </summary>
        public static string ProjectURL => @"https://github.com/rxi/flux";

        /// <summary>
        /// 原作者。
        /// </summary>
        public static string Author => "rxi";

        /// <summary>
        /// 原版本。
        /// </summary>
        public static string Version => "0.1.5";

        private HashSet<Tween> _tweens;
        private Queue<Tween> _removeQueue;

        public bool IsRunning { get; set; } = true;

        public Flux()
        {
            _tweens = new HashSet<Tween>();
            _removeQueue = new Queue<Tween>();
        }

        public void Update(float dt)
        {
            if (IsRunning == false) return;

            foreach (var tween in _tweens)
            {
                tween.Update(dt);
                if (tween.Rate > 1 && tween.IsLoop == false)
                    _removeQueue.Enqueue(tween);
            }

            while (_removeQueue.Count > 0)
            {
                var removedObject = _removeQueue.Dequeue();
                _tweens.Remove(removedObject);
                removedObject.RaiseCompletedEvent();
            }
        }

        /// <summary>
        /// 创建过渡对象，但是不会直接添加到对象列表里。
        /// </summary>
        /// <param name="duration">过渡动画播放的时间。</param>
        /// <param name="delay">过渡动画开始的时间延迟。</param>
        /// <param name="from">过渡动画的起始点。</param>
        /// <param name="to">过渡动画的结束点。</param>
        /// <returns></returns>
        public Tween CreateTween(float duration, float delay, float from, float to)
        {
            return new Tween(duration, delay, from, to);
        }

        /// <summary>
        /// 添加过渡对象，过渡对象不能重复。
        /// </summary>
        /// <param name="tween"></param>
        public Tween AddTween(Tween tween)
        {
            if (_tweens.Contains(tween)) return  tween;
            _tweens.Add(tween);
            return tween;
        }

        /// <summary>
        /// 创建并添加过渡对象，该方法可以直接添加到对象列表里。
        /// </summary>
        /// <param name="duration">过渡动画播放的时间。</param>
        /// <param name="delay">过渡动画开始的时间延迟。</param>
        /// <param name="from">过渡动画的起始点。</param>
        /// <param name="to">过渡动画的结束点。</param>
        /// <returns></returns>
        public Tween AddTween(float duration, float delay, float from, float to)
        {
            return AddTween(CreateTween(duration, delay, from, to));
        }

        /// <summary>
        /// 移除过渡动画。
        /// </summary>
        /// <param name="tween"></param>
        public void RemoveTween(Tween tween)
        {
            if (_tweens.Contains(tween))
            {
                _tweens.Remove(tween);
            }
        }

        public override string ToString()
        {
            var sb = new StringBuilder();
            int counter = 0;
            foreach (var item in _tweens)
            {
                counter++;
                sb.AppendLine($"[{counter}] progress {Math.Round(item.Rate * 100, 4)}%, value {Math.Round(item.CurrentValue, 4)}");
            }

            return sb.ToString();
        }

        /// <summary>
        /// 用于测试的可视化信息。
        /// </summary>
        public void DrawDebug()
        {
            int counter = 0;
            var fontHeight = Graphics.GetFont().GetHeight();
            foreach (var item in _tweens)
            {
                Graphics.SetColor(_debugColorParttern[counter % _debugColorParttern.Length]);
                item.DrawDebug();
                counter++;
            }
            counter = 0;
            foreach (var item in _tweens)
            {
                Graphics.SetColor(_debugColorParttern[counter % _debugColorParttern.Length]);
                Graphics.Print($"[{counter}] progress {Math.Round(item.Rate * 100, 4)}%, value {Math.Round(item.CurrentValue, 4)}", 0, fontHeight * counter);
                counter++;
            }

        }

        public IEnumerator<Tween> GetEnumerator()
        {
            return ((IEnumerable<Tween>)_tweens).GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return ((IEnumerable)_tweens).GetEnumerator();
        }


        public static Flux Instance => _instance;
        private static Flux _instance = new Flux();
    }
}
